# -*- coding: utf-8 -*-
'''
Created on 04.Şub.2010

@authors:	Aşkın Yollu <askin@askin.ws>
            Erdem Artan <baDibere@gmail.com>

'''

from xml.dom.minidom import parse, Document, parseString
from liburl import DownloadThread
import bz2, urllib, os

# parse pisi-index and, return packages with versions
def parsePisiIndex(pisiIndex):
    packages = {}

    datasource = open(pisiIndex)
    dom = parse(datasource)

    package_nodes = dom.getElementsByTagName("Package")
    for pkg_node in package_nodes:
        try:
            name = pkg_node.getElementsByTagName("Name")[0].firstChild.nodeValue
            version = pkg_node.getElementsByTagName("Version")[0].firstChild.nodeValue
            release = pkg_node.getElementsByTagName("Update")[0].getAttribute("release")
            package_size = pkg_node.getElementsByTagName("PackageSize")[0].firstChild.nodeValue
            package_hash = pkg_node.getElementsByTagName("PackageHash")[0].firstChild.nodeValue
            package_url = pkg_node.getElementsByTagName("PackageURI")[0].firstChild.nodeValue

            packages[name] = (version, release, package_size, package_hash, package_url)
        except:
            pass

    return packages

def parseInstalledPackageXML(installedXml):
    packages = []

    datasource = open(installedXml)
    dom = parse(datasource)

    repo_nodes = dom.getElementsByTagName("Repo")

    ''' structure example
        {
            "contrib": {"pkg2" : ("pkg1, "1.0", "2"), "pkg2" : ("pkg2", "3.5", "4")},
            "pardus-2009" : {"pkg2" : ("pkg1, "1.0", "2"), "pkg2" : ("pkg2", "3.5", "4")}
        }
    '''
    installed_package_with_repo = {}
    for repo_node in repo_nodes:
        repo = repo_node.getAttribute("repo")
        repo_uri = repo_node.getAttribute("repo_uri")
        for pkg in repo_node.getElementsByTagName("package"):
            name = pkg.getElementsByTagName("name")[0].firstChild.nodeValue
            version = pkg.getElementsByTagName("version")[0].firstChild.nodeValue
            release = pkg.getElementsByTagName("release")[0].firstChild.nodeValue

            try:
                installed_package_with_repo[repo][name] = (name, version, release, repo_uri)
            except:
                installed_package_with_repo[repo] = {}
                installed_package_with_repo[repo][name] = (name, version, release, repo_uri)

    return installed_package_with_repo

def getUpdatedPackages(oldDB, freshDB):
    updates = []
    for repo in oldDB:
        for pkg in oldDB[repo]:
            try:
                old_name, old_version, old_release, repo_url = oldDB[repo][pkg]
                fresh_name = pkg
                fresh_version = freshDB[pkg][0]
                fresh_release = freshDB[pkg][1]
                version, release, package_size, package_hash, package_url = freshDB[pkg]

                if(fresh_version > old_version):
                    updates.append({"name" : pkg,
                                    "version" : version,
                                    "release" : release,
                                    "size" : package_size,
                                    "hash" : package_hash,
                                    "url" : "%s%s" % (repo_url, package_url)})
                elif(fresh_release > old_release):
                    updates.append({"name" : pkg,
                                    "version" : version,
                                    "release" : release,
                                    "size" : package_size,
                                    "hash" : package_hash,
                                    "url" : "%s%s" % (repo_url, package_url)})
                else:
                    pass
            except:
                pass

    return updates

'''
Güncel PiSi indexi ile, kurulu paketleri karşılaştırarak
güncellenecek paketleri bulup, isim, indirme adresi gibi
bigileri updates.pdx dosyasına yazar

Bu fonksiyonun çalışabilmesi için daha önce güncellenecek
sistemden kurulu paketlerin listesi alınmalı, ardından
internet olan bir makinede pisi index elde edilip karşılaştırma
yapılmalı.
'''
def writeUpdatedPackages(installedPackageList, freshPackageList):
    # kurulu paketler
    currentDB = parseInstalledPackageXML(installedPackageList)
    # pisi indexin parse edilmesi
    freshDB = parsePisiIndex(freshPackageList)
    # kurulu paketlerle pisi indexin karşılaştırılması
    updates = getUpdatedPackages(currentDB, freshDB)
    writePDX(updates, "updates.pdx")

def writePDX(updates, fileName):
    # pdx'in oluşturulması
    doc = Document()
    # root element
    root = doc.createElement("PiSiDown")
    doc.appendChild(root)
    for pkg in updates:
        package = doc.createElement("Package")
        root.appendChild(package)

        name = doc.createElement("Name")
        package.appendChild(name)
        text = doc.createTextNode(pkg["name"])
        name.appendChild(text)

        url = doc.createElement("URI")
        package.appendChild(url)
        text = doc.createTextNode(pkg["url"])
        url.appendChild(text)

        pkghash = doc.createElement("Sha1Sum")
        package.appendChild(pkghash)
        text = doc.createTextNode(pkg["hash"])
        pkghash.appendChild(text)

    file = open(fileName, "w")
    doc.writexml(file)

'''
Güncellenecek paketlerin listesinin tutulduğu
pdx dosyasını okuyup gerekli bilgileri döndürür
formatı:
[
 {"name" : "pkg1", "url" : "http://depo/paket1.pisi" : "hash" : "36b1ff2ff6a5e21dfd69fa9be76702e6486f83fb"},
 {"name" : "pkg2", "url" : "http://depo/paket2.pisi" : "hash" : "36b1ff2ff6a5e21dfd69fa9be76702e6486f83fb"}
]
'''
def readPDX(fileName):
    packages = []
    dom = parse(open(fileName))

    pkg_nodes = dom.getElementsByTagName("Package")
    for pkg_node in pkg_nodes:
        name = pkg_node.getElementsByTagName("Name")[0].firstChild.nodeValue
        url = pkg_node.getElementsByTagName("URI")[0].firstChild.nodeValue
        pkg_hash = pkg_node.getElementsByTagName("Sha1Sum")[0].firstChild.nodeValue

        packages.append({"name": name, "url" : url, "hash" : pkg_hash})

    return packages

def getDownloadListHTML(updates, file_name):
    web_page = '''<head><title>PiSi Down Download List</title></head>
<html>
    <body>
        <ol>\n'''

    for pkg in updates:
        web_page += '            <li><a href="%s" target="_blank">%s - %s</a></li>\n' % (pkg[5], pkg[0], pkg[1])

    web_page += "        </ol>\n    <body>\n</html>\n"

    page_file = open(file_name, "w")
    page_file.write(web_page)

def getFreshPiSiIndex(installedList):
    dom = parse(open(installedList))
    repos = dom.getElementsByTagName("Repo")
    repo_addresses = []
    for repo in repos:
        repo_uri = repo.getAttribute("repo_uri")
        repo_addresses.append(repo_uri+"pisi-index.xml.bz2")
    print repo_addresses
    packages = []
    for uri in repo_addresses:
        try:
            print uri
            urllib.urlretrieve(uri,"pisi-index.xml.bz2")
            content = bz2.BZ2File("pisi-index.xml.bz2").read()
            os.remove("pisi-index.xml.bz2")
            dom = parseString(content)
            package = dom.getElementsByTagName("Package")
            for pack in package:
                if pack.getElementsByTagName("Name"):
                    packages.append(pack)
        except:
            pass
    doc = Document()
    root = doc.createElement("PISI")
    doc.appendChild(root)
    for package in packages:
        root.appendChild(package)
    file = open("freshPiSiList.xml", "w")
    doc.writexml(file)
    file.close()
    return "freshPiSiList.xml"

#Acaba Pardus mu kullanıyor?
def isPardus():
    try:
        import pisi
        return True
    except:
        return False

def checkInternet():
    try:
        import httplib
        connection = httplib.HTTPConnection('paketler.pardus.org.tr')
        connection.request("GET","/pardus-2009/pisi-index.xml.bz2")
        if connection.getresponse().status == 200:
            return True
        else:
            return False
    except:
        return False
    return False
